/********************************Copyright (c)**********************************\
**
**                   (c) Copyright 2021, Main, China, QD.
**                           All Rights Reserved
**
**                                 By(wo4fisher)
**                           http://www.wo4fisher.com
**
**----------------------------------文件信息------------------------------------
** 文件名称: key.c
** 创建人员: wht
** 创建日期: 2021-06-09
** 文档描述:
**
**----------------------------------版本信息------------------------------------
** 版本代号: V0.1
** 版本说明: 初始版本
**
**------------------------------------------------------------------------------
\********************************End of Head************************************/
#include "bsp_key.h"

/*******************************************************************************
** 函数名称: key_init
** 功能描述:
** 参数说明: None
** 返回说明: None
** 创建人员: wht
** 创建日期: 2019-02-18
**------------------------------------------------------------------------------
** 修改人员:wht
** 修改日期:
** 修改描述:
**------------------------------------------------------------------------------
********************************************************************************/
void  key_init(void)
{
	KEY1 = 1;
	KEY2 = 1;
	KEY3 = 1;
	KEY4 = 1;
	KEY5 = 1;
}


uint8 key_ScanKeyCode(void)
{
	/*TEST_KEY on the head board.*/
	if (KEY1 == 0) return KEY_DOWN;
	if (KEY2 == 0) return KEY_RIGHT;
	if (KEY3 == 0) return KEY_UP;
	if (KEY4 == 0) return KEY_MID;
	if (KEY5 == 0) return KEY_LEFT;
	/*No key pressed, return key_none.*/
	return KEY_NONE;
}

void key_Task(void)
{
	uint8 key_code;
	unsigned long ticks = tick_GetTicks();
	static unsigned long idata oldticks;
	static uint8 idata old_code, state = 0;
	switch (state)
	{
	case 0:
		old_code = key_ScanKeyCode();
		if (old_code == KEY_NONE) break;
		oldticks = ticks;
		state = 1;
		break;
	case 1: /*de-bounce*/
		if (ticks - oldticks < 4) break;
		key_code = key_ScanKeyCode();
		if (key_code == old_code)
		{
			key_InsertKeyCode(key_code, KEY_PRESSED);
			EA = 0;
			play_beep();
			EA = 1;
			oldticks = ticks;
			state = 2;
		}
		else
		{
			state = 0;
		}
		break;
	case 2: /*Check for repeat*/
		key_code = key_ScanKeyCode();
		if (key_code == KEY_NONE)
		{
			oldticks = ticks;
			state = 3;
		}
		else
		{
			if (ticks - oldticks > 50)
			{
				key_InsertKeyCode(old_code, KEY_REPEATED);
				EA = 0;
				play_beep();
				EA = 1;
				oldticks = ticks;
			}
		}
		break;
	case 3: /*check for release*/
		if (ticks - oldticks < 5) break;
		key_code = key_ScanKeyCode();
		if (key_code == KEY_NONE)
		{
			key_InsertKeyCode(old_code, KEY_RELEASED);
			state = 0;
		}
		else
		{
			oldticks = ticks;
		}
		break;
	default:
		break;
	}
}

#define KEY_FIFOLEN 4
static struct _key_fifo_tag_
{
	uint8 keycode[KEY_FIFOLEN];
	uint8 state[KEY_FIFOLEN];
	uint8 rear;
	uint8 top;
} idata g_key_fifo;

uint8 key_GetKeyCode(uint8 *pcode, uint8 *pstate)
{
	uint8 rear = g_key_fifo.rear;
	if (rear != g_key_fifo.top)
	{
		if (pcode != NULL)*pcode = g_key_fifo.keycode[rear];
		if (pstate != NULL)*pstate = g_key_fifo.state[rear];
		rear++;
		if (rear >= KEY_FIFOLEN) rear = 0;
		g_key_fifo.rear = rear;
		return 1;
	}
	return 0;
}

uint8 key_InsertKeyCode(uint8 keycode, uint8 state)
{
	uint8 top, next;

	top = g_key_fifo.top;
	next = g_key_fifo.top + 1;
	if (next >= KEY_FIFOLEN) next = 0;
	if (next != g_key_fifo.rear)
	{
		g_key_fifo.keycode[top] = keycode;
		g_key_fifo.state[top] = state;
		g_key_fifo.top = next;
		return 1;
	}
	return 0;
}


/********************************End of File************************************/